package com.dc.ai.security.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import com.dc.ai.security.constant.JwtClaimConstants;
import com.dc.ai.security.constant.SecurityConstants;
import com.dc.ai.security.model.SysUserDetails;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Jwt 工具类
 * @author zhangpan
 */
@Component
public class JwtUtils {

    /**
     * JWT 加解密使用的密钥
     */
    private static  byte[] key;

    /**
     * JWT Token 的有效时间(单位:秒)
     */
    private static int ttl;

    @Value("${jwt.key}")
    public void setKey(String key) {
        JwtUtils.key = key.getBytes();
    }

    @Value("${jwt.ttl}")
    public void setTtl(int ttl) {
        JwtUtils.ttl = ttl;
    }


    public static String generateToken(Authentication authentication,RedisTemplate<String,Object> redisTemplate) {

        SysUserDetails userDetails = (SysUserDetails) authentication.getPrincipal();
        Map<String,Object> payload = new HashMap<>();
        payload.put(JwtClaimConstants.USER_ID,userDetails.getUserId()); // 用户Id
        Date now = new Date();
        Date expiration = DateUtil.offsetSecond(now,ttl);

        payload.put(JWTPayload.ISSUED_AT,now);
        payload.put(JWTPayload.EXPIRES_AT,expiration);
        payload.put(JWTPayload.SUBJECT,authentication.getName());
        payload.put(JWTPayload.JWT_ID, IdUtil.simpleUUID());

        //将用户token信息放入缓存
        redisTemplate.opsForValue().set(SecurityConstants.USER_TOKEN_PREFIX + payload.get(JwtClaimConstants.USER_ID) ,payload.get(JWTPayload.JWT_ID),ttl, TimeUnit.SECONDS);
        return JWTUtil.createToken(payload,JwtUtils.key);
    }


    /**
     * 从JWT token 中解析authentication 用户认证信息
     * @param payload JWT 载体
     * @return 用户认证信息
     */
    public static UsernamePasswordAuthenticationToken getAuthentication(Map<String,Object> payload) {

        SysUserDetails userDetails = new SysUserDetails();
        userDetails.setUserId(Convert.toStr(payload.get(JwtClaimConstants.USER_ID)));

        userDetails.setUsername(Convert.toStr(payload.get(JWTPayload.SUBJECT))); // 用户名
        // 角色集合
        Set<SimpleGrantedAuthority> authorities = new HashSet<>();
        return new UsernamePasswordAuthenticationToken(userDetails, "", authorities);

    }

    /**
     * 解析JWT token 获取载体信息
     * @param token
     * @return
     */
    public static Map<String, Object> parseToken(String token) {

        try {
            if (StrUtil.isBlank(token)) {
                return null;
            }
            if (token.startsWith("Bearer")) {
                token = token.substring(7);
            }
            JWT jwt = JWTUtil.parseToken(token);
            if (jwt.setKey(JwtUtils.key).validate(0)) {
                return jwt.getPayloads();
            }
        }catch (Exception ignored) {
        }
        return null;
    }
}
